/**
	COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
	WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
    WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
    DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
    THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
    IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
    YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
    COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
    OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
    ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
	
	Copyright (c) 2012 Log n Sagl, Chiasso (CH)
	@version: 1.0
	@author: nicos.giuliani@logn.ch
	Website: http://www.logn.ch	
*/
String.prototype.compress = function() {
	return this.removeTabs().removeComments().toOneLine();
};
String.prototype.removeSpaces = function() {
	return this.replace(/\s/g, "");
};
String.prototype.removeTabs = function() {
	return this.replace(/\r/g, "");
};
String.prototype.toOneLine = function() {
	return this.replace(/\n/g, "");
};
String.prototype.removeComments = function() {
	return this.replace(/([^\/"']+|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|\/\*(?:[^*]|\*+[^*\/])*\*+\/|\/\/.*/, "");
};
Element.prototype.bind =  function(ev, callback) {
	return this.addEventListener(ev, callback);
};
Array.prototype.indexOfId = function(id) {
	for(var i = 0; i < this.length; i++) {
		if(this[i].id == id) {
			return i;
		}
	}
	return -1;
};
Array.prototype.getElementById = function(id) {
	for(var i = 0; i < this.length; i++) {
		if(this[i].id == id) {
			return this[i].el;
		}
	}
	return null;
};
function getArgsName(f) {
 	var funStr = f.toString();
    return funStr.slice(funStr.indexOf('(')+1, funStr.indexOf(')')).match(/([^\s,]+)/g);
};

function getElement(selector) {
	return document.querySelector(selector);
};

function Class(parent, object) {

	object._super = parent;
	return object;
};

function load(path) {

	if(!path || path == null) return;

	var req = new XMLHttpRequest(), success = false;
	req.open('GET', path, false);
	req.send();

	if (req.status === 200 || req.status === 0) {
		success = true;
	}

	return {
		success : success,
		status : req.status,
		response : req.responseText
	};
};


/**
 * Application
 */
var App = function(params) {

	/** Loads & sets settings file */
	eval('this.settings = ' + load('protected/config/main.js').response.removeComments().removeTabs());
	/** Import model --> */
	eval(load('protected/models/model.js').response.removeComments().removeTabs()+";\n");	
	/** Import controller --> */
	eval(load('protected/controllers/controller.js').response.removeComments().removeTabs()+";\n");	
		
	/**
	 * Given a model name, fetches & loads it into the app.
	 * @param: String {name}
	 * @return: Model {model}
	 */
	this.loadModel = function(name) {
		
		try {
			
			if(!self.models[name]) {

				try {
					var text = load('protected/models/'+name+'.js').response, json = JSON.parse(text);
					this.models[name] = new Model(json);
				}catch(e) {
					console.log('failed loading model. Error: '+e);
				}
			}
			return this.models[name];
			
		} catch(e) {
			console.log('Error while loading model '+name+'. Message:'+e);
			return null;
		}
	};
	
	
	/**
	 * Given an url, loads a js script
	 * @param: String url
	 * @return: Void
	 */
	this.loadScript = function(url) {
		
		var script = document.createElement("script");
		script.setAttribute("type", "text/javascript");
		script.setAttribute("src", url);
		document.getElementsByTagName("head")[0].appendChild(script);	
	};


	/**
	 * Internal language object. Provides translations.
	 */
	this.language = {
	
		current:false,
		files:[],
	
		getFile : function(lang) {
			
			if(this.files[lang]) return this.files[lang];
			
			var req = new XMLHttpRequest();
			req.async = false;
			req.open('GET', 'protected/models/languages/' + lang + '.js', false);
			req.send();			
			
			if (req.status !== 200) {
				return false;
			}	
			this.files[lang] = req.responseText;		
			return req.responseText;
		},
	
		translate : function(text, lang) {
	
			var regExp = null, file = this.getFile(lang);
	
			if (!file) {
				return text;
			}
			try {
				eval('file = ' + file + ';');
			} catch(e) {
				console.log('Error while evaluating. Message: '+e);				
			}
	
			for (var i in file) {
	
				regExp = new RegExp('{' + i + '}', 'gm');
				text = text.replace(regExp, file[i]);
			}
			return text;
		},
	
		get : function() {
			
			var v = arguments, s = '';
			if(this.current) {
				
				for(var i=0;i<v.length;i++) {
					s+= ' '+ this.current[v[i]];
				}
				return s;
			}
			
			var lang = localStorage.getItem(Sha1.hash('rm-lang')) ? localStorage.getItem(Sha1.hash('rm-lang')) : 'en';
			eval('var file = ' + this.getFile(lang));
			this.current = file;
			
			for(var i=0;i<v.length;i++) {
				s+= ' '+file[v[i]];
			}
			return s;
		}
	};
	
	/**
	 * Loads all libraries set in main.js
	 * @return: Void 
	 */
	this.loadLibraries = function() {		

		for(var i=0;i < this.settings.libraries.length;i++) {
			this.loadScript('protected/libraries/'+this.settings.libraries[i]);
		}
	};

	/**
	 * Loads all components set in main.js
	 * @return: Void 
	 */
	this.loadComponents = function() {		

		for(var i=0;i < this.settings.components.length;i++) {
			this.loadScript('protected/components/'+this.settings.components[i]);
		}
	};
	
	/** 
	 * +---------------------------------------------------------------------------------------------------------+
	 * |                                    Application constructor                                              |
	 * +---------------------------------------------------------------------------------------------------------+
	 */
	
	try {

		var self = this;
	
		this.components = [];
		this.models = [];
		
		this.loadLibraries();
		this.loadComponents();
		this.settings.init();
		
		this.controller = new Controller(this);

		
	} catch(e) {
		console.log(e);
	}
};